package com.zhanghe.springsecurity.provider;

import com.zhanghe.springsecurity.Service.TokenService;
import com.zhanghe.springsecurity.Service.UserService;
import com.zhanghe.springsecurity.authentication.JWTAuthenticationToken;
import com.zhanghe.springsecurity.exception.TokenExpiredException;
import com.zhanghe.springsecurity.exception.TokenMalformationException;
import com.zhanghe.springsecurity.model.User;
import io.jsonwebtoken.ExpiredJwtException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import org.springframework.security.core.AuthenticationException;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * RefreshCustomAuthenticationProvider
 *
 * @author Clevo
 * @date 2018/4/18
 */
public class RefreshCustomAuthenticationProvider implements AuthenticationProvider {

    private static final Logger logger = LoggerFactory.getLogger(RefreshCustomAuthenticationProvider.class);

    @Autowired
    private UserService userService;

    @Autowired
    private TokenService tokenService;

    @Value("${gnnt.auth.refresh_token_expirationminutes}")
    private long refresh_token_expirationminutes;

    public RefreshCustomAuthenticationProvider() {
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        logger.debug("进入刷新令牌验证器");
        String token = ((JWTAuthenticationToken) authentication).getRefresh_token();
        try {
            String name = tokenService.getValueFromToken(token, "sub").toString();
            User user = userService.loadUserByUsername(name);
            // 认证逻辑
            if (user != null) {
                logger.debug("用户:" + name + " 令牌验证通过 生成新令牌");
                // 这里设置权限和角色
                ArrayList<GrantedAuthority> authorities = new ArrayList<>();
                for (String role : new ArrayList<String>() {{
                    add("ROLE_ADMIN");
                    add("ROLE_SELLER");
                }}) {
                    authorities.add(new SimpleGrantedAuthority(role));
                }
                // 生成令牌
                Authentication auth = new JWTAuthenticationToken(tokenService.sign(name, new HashMap<>(), refresh_token_expirationminutes), authorities);
                return auth;
            } else {
                logger.debug("用户:" + name + " 令牌错误 错误令牌:" + token);
                throw new BadCredentialsException("令牌错误~");
            }
        } catch (ExpiredJwtException e) {
            logger.debug("用户 refresh令牌过期 过期令牌:" + token);
            throw new TokenExpiredException("令牌过期");
        } catch (Exception e) {
            logger.debug("用户 refresh令牌不合法:" + token);
            throw new TokenMalformationException("令牌不合法");
        }
    }

    // 是否可以提供输入类型的认证服务
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(JWTAuthenticationToken.class);
    }
}
